﻿using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Weazel.Gezel.Model.Errors;
using Weazel.Gezel.Model;
using Weazel.Gezel.Parser;

namespace BadgerTest
{	
	/// <summary>
	/// This class contains various methods used by the tests in the project.
	/// </summary>
	public static class BadgerTestUtillities
	{
		/// <summary>
		/// Get an embedded resource
		/// </summary>
		/// <param name="resource">name of the resource</param>
		/// <returns>string content</returns>
		public static string GetResourceFile(string resource)
		{
			Assembly assembly = Assembly.GetExecutingAssembly();
			Stream stream = assembly.GetManifestResourceStream("BadgerTest." + resource);
			StreamReader reader = new StreamReader(stream);

			string file = reader.ReadToEnd();

			reader.Close();
			stream.Close();

			return file;
		}

		/// <summary>
		/// Return the content of a file as a string
		/// </summary>
		/// <param name="file">file to read</param>
		/// <returns></returns>
		public static string ReadFile(string file)
		{
			FileStream fileStream = null;
			StreamReader reader = null;
			string content = null;

			try
			{
				fileStream = File.Open(file, FileMode.Open);
				reader = new StreamReader(fileStream);
				content = reader.ReadToEnd();
			}
			finally
			{
				if (reader != null)
					reader.Close();

				if (fileStream != null)
					fileStream.Close();
			}

			return content;
		}

		/// <summary>
		/// Parse and verify a gezel description.
		/// </summary>
		/// <param name="description">the gezel description to parse and verify</param>
		/// <param name="parseErrors">number of expected warnings</param>
		/// <returns>Model as given in description</returns>
		public static Model ParseAndVerify(string description, int expectedWarnings)
		{
			List<ParseError> parseErrors = null;
			List<VerificationError> verificationErrors = null;
			List<VerificationWarning> warnings = null;

			parseErrors = new List<ParseError>();
			Model model = ParseModel.Parse(ref parseErrors, description);
			model.Verify(ref verificationErrors, ref warnings);

			Assert.AreEqual(0, parseErrors.Count);    
			Assert.AreEqual(0, verificationErrors.Count);

			Assert.AreEqual(expectedWarnings, warnings.Count);
			return model;
		}

		/// <summary>
		/// Create a design library using ModelSim
		/// </summary>
		/// <param name="workingDir">working directory</param>
		/// <param name="library">name of library to create</param>
		public static void RunVLib(string workingDir, string library)
		{
			Process p = new Process();
			p.StartInfo.WorkingDirectory = workingDir;
			p.StartInfo.FileName = "vlib";
			p.StartInfo.Arguments = library;
			p.Start();
			p.WaitForExit();
		}

		/// <summary>
		/// Run the ModelSim vhdl compiler
		/// </summary>
		/// <param name="workingDir">working directory</param>
		/// <param name="file">file within the working direcetory to compile</param>
		public static void RunVCom(string workingDir, string file)
		{
			Process p = new Process();
			p.StartInfo.WorkingDirectory = workingDir;
			p.StartInfo.FileName = "vcom";
			p.StartInfo.Arguments = file;		
			p.Start();
			p.WaitForExit();

			if (p.ExitCode != 0)
				throw new Exception("Compilation failed for file: " + file);
		}

		/// <summary>
		/// Run the ModelSim vhdl simulator 
		/// </summary>
		/// <param name="workingDir">working directory</param>
		/// <param name="entity">top entity (used for simulation)</param>
		/// <param name="simulationCommands">list of commands for the simulator (; seperated)</param>
		public static void RunVSim(string workingDir, string entity, string simulationCommands)
		{
			Process p = new Process();
			p.StartInfo.WorkingDirectory = workingDir;
			p.StartInfo.FileName = "vsim";
			p.StartInfo.Arguments = string.Format("-c -do \"{0}; quit\" {1}", simulationCommands, entity);
			p.Start();
			p.WaitForExit();
		}
	}
}
